import watcher from './tui-watch'
Component({
  options: {
    multipleSlots: true
  },
  properties: {
    padding: {
      type: String,
      value: ''
    },
    marginTop: {
      type: String,
      optionalTypes: [Number],
      value: 0
    },
    marginBottom: {
      type: String,
      optionalTypes: [Number],
      value: 0
    },
    label: {
      type: String,
      value: ''
    },
    labelSize: {
      type: String,
      optionalTypes: [Number],
      value: 0
    },
    labelColor: {
      type: String,
      value: ''
    },
    //V2.3.0+
    labelFontWeight: {
      type: String,
      optionalTypes: [Number],
      value: 0
    },
    labelWidth: {
      type: String,
      optionalTypes: [Number],
      value: 160
    },
    labelRight: {
      type: String,
      optionalTypes: [Number],
      value: 16
    },
    asterisk: {
      type: Boolean,
      value: false
    },
    asteriskColor: {
      type: String,
      value: ''
    },
    background: {
      type: String,
      value: ''
    },
    highlight: {
      type: Boolean,
      value: false
    },
    arrow: {
      type: Boolean,
      value: false
    },
    arrowColor: {
      type: String,
      value: ''
    },
    bottomBorder: {
      type: Boolean,
      value: true
    },
    borderColor: {
      type: String,
      value: ''
    },
    left: {
      type: String,
      optionalTypes: [Number],
      value: 30
    },
    right: {
      type: String,
      optionalTypes: [Number],
      value: 0
    },
    radius: {
      type: String,
      value: ''
    },
    index: {
      type: String,
      optionalTypes: [Number],
      value: 0
    },
    //表单域 model 字段，在使用校验时该属性是必填的
    prop: {
      type: String,
      value: ''
    },
    //错误提示信息布局方式是否使用绝对定位
    absolute: {
      type: Boolean,
      value: true
    },
    //错误提示位置：1-标题左对齐 2-内容左对齐 3-居右对齐
    position: {
      type: String,
      optionalTypes: [Number],
      value: 0
    },
    //表单验证规则，如果平台不支持前套传入函数，请使用setRules方法传入
    rules: {
      type: Object,
      value: {}
    }
  },
  relations: {
    '../tui-form/tui-form': {
      type: 'ancestor',
      linked: function (target) {
        this.data.form = target
        this.init()
      }
    }
  },
  data: {
    form: null,
    g_padding: (wx.$tui && wx.$tui.tuiFormItem.padding) || '28rpx 30rpx',
    g_background: (wx.$tui && wx.$tui.tuiFormItem.background) || '#fff',
    g_radius: (wx.$tui && wx.$tui.tuiFormItem.radius) || '0',
    g_asteriskColor: (wx.$tui && wx.$tui.tuiFormItem.asteriskColor) || '#EB0909',
    g_arrowColor: (wx.$tui && wx.$tui.tuiFormItem.arrowColor) || '#c0c0c0',
    g_borderColor: (wx.$tui && wx.$tui.tuiFormItem.borderColor) || '#eaeef1',
    g_labelSize: (wx.$tui && wx.$tui.tuiFormItem.labelSize) || 32,
    g_labelColor: (wx.$tui && wx.$tui.tuiFormItem.labelColor) || '#333',
    g_labelFontWeight: (wx.$tui && wx.$tui.tuiFormItem.labelFontWeight) || 400,
    g_position: (wx.$tui && wx.$tui.tuiFormItem.position) || 2,
    errorMsg: '',
    showError: false,
    itemValue: '',
    watchKey: '',
    //是否即时校验
    isImmediate: false,
    err_right: 0,
    err_left: 0,
    //item项自己的rules
    formItemRules: null
  },
  lifetimes: {
    detached: function () {
      this.uninstall()
    }
  },
  methods: {
    getErrorRight() {
      //padding值不可为空，因为需要放置错误信息
      const padding = this.data.padding || this.data.g_padding
      const arr = padding.split(' ')
      return arr[1] || arr[0] || '30rpx'
    },
    getErrorLeft() {
      const position = this.data.position || this.data.g_position
      let left = '30rpx'
      const pr = this.getErrorRight()
      if (position == 2) {
        const pdr = pr ? pr.replace('rpx', '').replace('px', '') : 0;
        left = (Number(this.data.labelWidth) + Number(pdr)) + 'rpx'
      }
      this.setData({
        err_right: pr,
        err_left: left
      })
    },
    init() {
      const form = this.data.form;
      form.data.childrenArr.push(this)
      this.setData({
        //主要用于动态表单初始化值
        isImmediate: form.data.isImmediate,
        showError: form.data.showMessage ? false : true,
      }, () => {
        this.getErrorLeft()
      })
    },
    watchHandler(val) {
      const key = this.data.prop || 'prop_key_empty'
      let watch = {}
      let model = {}
      const instance = this
      watch[key] = function (val) {
        if (instance.data.isImmediate && instance.data.prop && instance.data.form) {
          model[key] = val
          instance.data.form.immediateValidator(model, key).then(res => {
            instance.setData({
              errorMsg: res.isPass ? '' : res.errorMsg
            })
          }).catch(err => {
            console.log(err.errorMsg)
          })
        } else {
          if (instance.data.showError && val != instance.data.itemValue) {
            instance.setData({
              errorMsg: ''
            })
          }
        }
      }
      return watch
    },
    setWatcherPageProp(instance) {
      const form = this.data.form
      if (form && this.data.prop && this.data.prop !== true && this.data.watcherKey !== this.data.prop) {
        this.data.watcherKey = this.data.prop
        watcher.setWatcher(instance, this.watchHandler())
      }
    },
    //是否开启即时校验
    immediateValidate(isOpen) {
      this.data.isImmediate = isOpen;
    },
    // Form组件获取当前FormItem 项 rules数据
    getRules() {
      //优先使用setRules 方法传入的rules值
      const rules = this.data.formItemRules || this.data.rules
      if (!rules.name && (rules.rule || rules.validator)) {
        rules['name'] = this.data.prop
      }
      //当未传入prop则不进行校验
      return !rules.name ? null : rules
    },
    //设置校验规则
    setRules(rules) {
      this.data.formItemRules = rules
    },
    //设置校验规则，并合并或替换Form组件中该prop对应的rules【当页面调用Form组件校验方法传入rules时进行合并操作】
    //该方法作为备用方法，如果有需要再进行放开【仅当动态formItem组件，并且当前rules未设置在总rules数据里时使用】
    setRulesMerge(rules) {
      this.data.formItemRules = rules || this.data.rules
      const form = this.data.form
      if (form) {
        const index = form.data.concatRules.findIndex(e => e.name === rules.name || e.name === this.data.prop)
        const rule = this.getRules()
        if (!rule) return;
        if (index === -1) {
          form.data.concatRules.push(rule)
        } else {
          form.data.concatRules[index] = rule
        }
      }
    },
    /**
     * 验证方法
     * @param {any} value 值，不传则使用Form组件model中值
     */
    validate(value) {
      const rules = this.getRules()
      const form = this.data.form
      return new Promise((resolve, reject) => {
        if (form && rules) {
          const model = {}
          let val = value;
          if (val === undefined || val === null) {
            val = form.data.model[rules.name] || null
          }
          model[rules.name] = val;
          form.immediateValidator(model, rules.name, [rules]).then(res => {
            if (res.isPass) {
              this.setData({
                errorMsg: ''
              })
            } else {
              this.setData({
                errorMsg: res.errorMsg
              })
            }
            resolve(res)
          }).catch(err => {
            reject(err)
            console.log(err.errorMsg)
          })
        } else {
          reject({
            isPass: false,
            errorMsg: '未检测到Form组件或rules校验规则数据！'
          })
        }
      })
    },
    clearValidate() {
      this.setData({
        errorMsg: ''
      })
    },
    uninstall() {
      const form = this.data.form
      form && form.uninstall(this)
    },
    handleClick() {
      this.triggerEvent('click', {
        index: this.data.index
      });
    }
  }
})